CMAKE_MINIMUM_REQUIRED (VERSION 2.8.5)
SET(CAPN_LIB_NAME "capn")
PROJECT("libcapn" C)

OPTION (BUILD_SHARED_LIBS "Build shared libraries." ON)

SET(CMAKE_VERBOSE_MAKEFILE OFF)

SET(CAPN_VERSION_MAJOR 2)
SET(CAPN_VERSION_MINOR 0)
SET(CAPN_VERSION_PATCH 0)

SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")

INCLUDE (CheckFunctionExists)
INCLUDE (CheckIncludeFiles)
INCLUDE (CheckSymbolExists)
INCLUDE (CheckTypeSize)

SET(CAPN_VERSION "${CAPN_VERSION_MAJOR}.${CAPN_VERSION_MINOR}.${CAPN_VERSION_PATCH}")
SET(PROJECT_VERSION ${CAPN_VERSION})

IF(NOT DEFINED CMAKE_BUILD_TYPE)
    SET(CMAKE_BUILD_TYPE "Release")
ENDIF()

STRING(REPLACE "/" ";" CAPN_CC_LIST ${CMAKE_C_COMPILER})
LIST(GET CAPN_CC_LIST -1 CAPN_CC)

IF("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
    SET(CMAKE_C_FLAGS "-std=c99 -D_POSIX_C_SOURCE=200112L -Wno-deprecated -Wall -Wextra -Wimplicit -fPIC -W -Wformat-security -pedantic -Wno-pointer-bool-conversion")
    SET(CMAKE_C_FLAGS_DEBUGE "-g3 -O0 -DDEBUG")
    SET(CMAKE_C_FLAGS_RELEASE "-g2 -O3")
ENDIF()

SET(CAPN_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
SET(CAPN_SOURCE_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/library")
SET(CAPN_THIRD_PARTY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/third_party")

SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}")
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}")

INCLUDE_DIRECTORIES (${CAPN_SOURCE_LIB_DIR})
INCLUDE_DIRECTORIES (${PROJECT_BINARY_DIR})
INCLUDE_DIRECTORIES ("${PROJECT_BINARY_DIR}/src/library")

CHECK_INCLUDE_FILES (ctype.h APN_HAVE_CTYPE_H)
CHECK_INCLUDE_FILES (inttypes.h APN_HAVE_INTTYPES_H)
CHECK_INCLUDE_FILES (stdint.h APN_HAVE_STDINT_H)
CHECK_INCLUDE_FILES (unistd.h APN_HAVE_UNISTD_H)
CHECK_INCLUDE_FILES (netinet/in.h APN_HAVE_NETINET_IN_H)
CHECK_INCLUDE_FILES (arpa/inet.h APN_HAVE_ARPA_INET_H)
CHECK_INCLUDE_FILES (netdb.h APN_HAVE_NETDB_H)
CHECK_INCLUDE_FILES (fcntl.h APN_HAVE_FCNTL_H)
CHECK_INCLUDE_FILES (sys/socket.h APN_HAVE_SYS_SOCKET_H)
CHECK_INCLUDE_FILES (strings.h APN_HAVE_STRINGS_H)
CHECK_INCLUDE_FILES (arpa/inet.h APN_HAVE_NETINET_IN_H)

IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
    SET(CAPN_ARCH_STR "x86_64")
    SET(CAPN_ARCH_X86_64 TRUE)
ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8)
    SET(CAPN_ARCH_STR "x86")
    SET(CAPN_ARCH_X86_64 FALSE)
ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8)

IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
    SET(OS_LINUX TRUE)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")

CHECK_FUNCTION_EXISTS (strerror_r HAVE_STRERROR_R)

MACRO(CAPN_TEST_STRERROR_R HEADER)
    MESSAGE(STATUS "Performing test ${HEADER}")
    TRY_RUN(${HEADER} ${HEADER}_res ${CMAKE_BINARY_DIR} "${CMAKE_SOURCE_DIR}/cmake/tests/strerror_r.c"
	    CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=-D${HEADER}
	    OUTPUT_VARIABLE OUTPUT
    )
    IF(${HEADER}_res AND NOT ${HEADER})
	    SET(${HEADER} 1 CACHE INTERNAL "test ${HEADER}")
	    MESSAGE(STATUS "Performing test ${HEADER} - Success")
    ELSE()
	    SET(${HEADER} "" CACHE INTERNAL "test ${HEADER}")
	    MESSAGE(STATUS "Performing test ${HEADER} - Failed")
    ENDIF()
ENDMACRO()

FOREACH(STRERROR_R_HEADER
    APN_HAVE_GLIBC_STRERROR_R
    APN_HAVE_POSIX_STRERROR_R
)
CAPN_TEST_STRERROR_R(${STRERROR_R_HEADER})
ENDFOREACH(STRERROR_R_HEADER)

INCLUDE(ExternalProject)

INCLUDE_DIRECTORIES ("${CAPN_THIRD_PARTY_DIR}/jansson")
INCLUDE_DIRECTORIES ("${CAPN_THIRD_PARTY_DIR}/jansson/include")

CONFIGURE_FILE("${CAPN_SOURCE_LIB_DIR}/apn_platform.h.cmake" "${PROJECT_BINARY_DIR}/src/library/apn_platform.h")
CONFIGURE_FILE("${CAPN_SOURCE_LIB_DIR}/apn_version.h.cmake" "${PROJECT_BINARY_DIR}/src/library/apn_version.h")

SET(CAPN_SOURCE_FILES
        ${CAPN_SOURCE_LIB_DIR}/apn_memory.c
        ${CAPN_SOURCE_LIB_DIR}/apn.c
        ${CAPN_SOURCE_LIB_DIR}/apn_strings.c
        ${CAPN_SOURCE_LIB_DIR}/apn_payload.c
        ${CAPN_SOURCE_LIB_DIR}/apn_tokens.c
        ${CAPN_SOURCE_LIB_DIR}/apn_binary_message.c
        ${CAPN_SOURCE_LIB_DIR}/apn_array.c
        ${CAPN_SOURCE_LIB_DIR}/apn_strerror.c
        ${CAPN_SOURCE_LIB_DIR}/apn_ssl.c
        ${CAPN_SOURCE_LIB_DIR}/apn_log.c
        )

SET(CAPN_PUBLIC_HEADER_FILES
    ${CAPN_SOURCE_LIB_DIR}/apn.h
    ${CAPN_SOURCE_LIB_DIR}/apn_payload.h
    ${PROJECT_BINARY_DIR}/src/library/apn_platform.h
    ${PROJECT_BINARY_DIR}/src/library/apn_version.h
    ${CAPN_SOURCE_LIB_DIR}/apn_binary_message.h
    ${CAPN_SOURCE_LIB_DIR}/apn_array.h
)

IF(WIN32)
    SET(CAPN_INSTALL_DIR "${PROJECT_BINARY_DIR}/capn-bin")
    SET(CAPN_INSTALL_PATH_LIB "${CAPN_INSTALL_DIR}/lib")
    SET(CAPN_INSTALL_PATH_INCLUDES "${CAPN_INSTALL_DIR}/include")
    SET(CAPN_INSTALL_PATH_BIN "${CAPN_INSTALL_DIR}/bin")
	
    ExternalProject_Add(
        jansson
        SOURCE_DIR "${CAPN_THIRD_PARTY_DIR}/jansson"
        BINARY_DIR "${CAPN_THIRD_PARTY_DIR}/jansson"
        INSTALL_DIR "${CAPN_THIRD_PARTY_DIR}/jansson"
        CMAKE_COMMAND cmake . -DJANSSON_BUILD_DOCS=OFF
        BUILD_COMMAND nmake
        INSTALL_COMMAND ""
    )
	
    IF(MINGW)
        ADD_CUSTOM_COMMAND ( OUTPUT ${CAPN_SOURCE_LIB_DIR}/rc_capn.obj
        COMMAND windres.exe -I${CMAKE_CURRENT_SOURCE_DIR} -i${CMAKE_CURRENT_SOURCE_DIR}/win/capn.rc
                -o ${PROJECT_BINARY_DIR}/rc_capn.obj )
        LIST(APPEND SOURCE_FILES rc_capn.obj)
    ELSE()
		LIST(APPEND CAPN_SOURCE_FILES ${CAPN_SOURCE_LIB_DIR}/capn.rc)
    ENDIF()
	
    FILE (GLOB OPENSSL_HEADER_FILES ${CAPN_THIRD_PARTY_DIR}/openssl/win/include/openssl/*.h)
    INSTALL(FILES ${OPENSSL_HEADER_FILES} DESTINATION "${CAPN_INSTALL_PATH_INCLUDES}/openssl")

    INCLUDE_DIRECTORIES("${CAPN_THIRD_PARTY_DIR}/openssl/win/include")
	SET(OPENSSL_SSLEAY_LIBRARY "${CAPN_THIRD_PARTY_DIR}/openssl/win/lib/ssleay32.lib")
	SET(OPENSSL_LIBEAY_LIBRARY "${CAPN_THIRD_PARTY_DIR}/openssl/win/lib/libeay32.lib")

    CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/win_build/createpkg.bat.cmake" "${PROJECT_BINARY_DIR}/win_build/createpkg.bat")

    INSTALL(FILES
        ${CAPN_THIRD_PARTY_DIR}/openssl/win/lib/ssleay32.lib
	    ${CAPN_THIRD_PARTY_DIR}/openssl/win/lib/libeay32.lib
        DESTINATION ${CAPN_INSTALL_PATH_LIB})
          
    INSTALL(FILES
        ${CMAKE_CURRENT_SOURCE_DIR}/README.md
        ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE
        DESTINATION ${CAPN_INSTALL_DIR})

    	ADD_CUSTOM_TARGET(zip COMMAND "${PROJECT_BINARY_DIR}/win_build/createpkg.bat")
ELSE(WIN32)
    IF(UNIX)
	INCLUDE (FindOpenSSL)
        IF(NOT OPENSSL_FOUND)
            MESSAGE(FATAL_ERROR "openssl is not found!")
        ENDIF()
        INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIRS})

        IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
            SET(CMAKE_INSTALL_PREFIX "/usr")
        ENDIF()

        IF(NOT DEFINED CAPN_INSTALL_PATH_LIB)
            SET(CAPN_INSTALL_PATH_LIB "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "")
        ENDIF()

        IF(NOT DEFINED CAPN_INSTALL_PATH_INCLUDES)
            SET(CAPN_INSTALL_PATH_INCLUDES "${CMAKE_INSTALL_PREFIX}/include/${CAPN_LIB_NAME}"  CACHE PATH "")
        ENDIF()

        IF(NOT DEFINED CAPN_INSTALL_PATH_BIN)
            SET(CAPN_INSTALL_PATH_BIN "${CMAKE_INSTALL_PREFIX}/bin"  CACHE PATH "")
        ENDIF()

        IF(NOT DEFINED CAPN_INSTALL_PATH_PKGCONFIG)
            SET(CAPN_INSTALL_PATH_PKGCONFIG "${CMAKE_INSTALL_PREFIX}/share/pkgconfig"  CACHE PATH "")
        ENDIF()

        IF(LIB_SUFFIX)
            SET(CAPN_INSTALL_PATH_LIB "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}")
        ELSE()
            IF(CAPN_ARCH_X86_64 AND OS_LINUX)
            IF(EXISTS "${CMAKE_INSTALL_PREFIX}/lib64" AND IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/lib64")
                SET(CAPN_INSTALL_PATH_LIB "${CMAKE_INSTALL_PREFIX}/lib64")
            ENDIF()
            ENDIF()
        ENDIF()

        ExternalProject_Add(
            jansson
            SOURCE_DIR "${CAPN_THIRD_PARTY_DIR}/jansson"
            BINARY_DIR "${CAPN_THIRD_PARTY_DIR}/jansson"
            INSTALL_DIR "${CAPN_THIRD_PARTY_DIR}/jansson"
            CMAKE_COMMAND cmake . -DCMAKE_C_FLAGS=-fPIC -DJANSSON_BUILD_DOCS=OFF
            BUILD_COMMAND make
            INSTALL_COMMAND ""
        )
		
        SET(CAPN_INSTALL_PATH_LIB "${CAPN_INSTALL_PATH_LIB}/${CAPN_LIB_NAME}")
        SET(CAPN_PKGCONF_FILE_NAME "libcapn.pc")
        CONFIGURE_FILE("${CAPN_PKGCONF_FILE_NAME}.cmake" "${PROJECT_BINARY_DIR}/${CAPN_PKGCONF_FILE_NAME}")
        INSTALL(FILES "${PROJECT_BINARY_DIR}/${CAPN_PKGCONF_FILE_NAME}" DESTINATION ${CAPN_INSTALL_PATH_PKGCONFIG})

        IF(DEFINED OS_LINUX)
            IF(NOT DEFINED CAPN_INSTALL_PATH_SYSCONFIG)
                SET(CAPN_INSTALL_PATH_SYSCONFIG "/etc"  CACHE PATH "")
            ENDIF()
            IF(EXISTS "${CAPN_INSTALL_PATH_SYSCONFIG}/ld.so.conf.d" AND IS_DIRECTORY "${CAPN_INSTALL_PATH_SYSCONFIG}/ld.so.conf.d")
                SET(CAPN_LDCONF_FILE_NAME "libcapn-${CAPN_VERSION}-${CAPN_ARCH_STR}.conf")
                CONFIGURE_FILE(libcapn.ld.conf.cmake "${PROJECT_BINARY_DIR}/${CAPN_LDCONF_FILE_NAME}")
                INSTALL(FILES "${PROJECT_BINARY_DIR}/${CAPN_LDCONF_FILE_NAME}" DESTINATION "${CAPN_INSTALL_PATH_SYSCONFIG}/ld.so.conf.d")
            ENDIF()
        ENDIF()

        CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/src/config/apn_config.c.cmake" "${PROJECT_BINARY_DIR}/src/config/apn_config.c")
        ADD_EXECUTABLE("libcapn-config" "${PROJECT_BINARY_DIR}/src/config/apn_config.c")
        INSTALL(TARGETS "libcapn-config" DESTINATION ${CAPN_INSTALL_PATH_BIN})

        ADD_EXECUTABLE("apn-pusher" "${CMAKE_CURRENT_SOURCE_DIR}/src/pusher/pusher.c")
        TARGET_LINK_LIBRARIES("apn-pusher" "capn")
        INSTALL(TARGETS "apn-pusher" DESTINATION ${CAPN_INSTALL_PATH_BIN})

    ENDIF(UNIX)
ENDIF(WIN32)

IF(BUILD_SHARED_LIBS)
    ADD_LIBRARY(${CAPN_LIB_NAME} SHARED ${CAPN_SOURCE_FILES})
ELSE()
    ADD_LIBRARY(${CAPN_LIB_NAME} STATIC ${CAPN_SOURCE_FILES})
ENDIF()

IF(WIN32)
	TARGET_LINK_LIBRARIES(${CAPN_LIB_NAME} "${CAPN_THIRD_PARTY_DIR}/jansson/lib/jansson_d.lib")
	TARGET_LINK_LIBRARIES(${CAPN_LIB_NAME} Ws2_32.lib)
	TARGET_LINK_LIBRARIES(${CAPN_LIB_NAME} ${OPENSSL_SSLEAY_LIBRARY})
	TARGET_LINK_LIBRARIES(${CAPN_LIB_NAME} ${OPENSSL_LIBEAY_LIBRARY})
ELSE()
	TARGET_LINK_LIBRARIES(${CAPN_LIB_NAME} "${CAPN_THIRD_PARTY_DIR}/jansson/lib/libjansson.a")
	TARGET_LINK_LIBRARIES(${CAPN_LIB_NAME} ${OPENSSL_LIBRARIES})
ENDIF()

SET_TARGET_PROPERTIES(${CAPN_LIB_NAME} PROPERTIES
    VERSION ${CAPN_VERSION} SOVERSION ${CAPN_VERSION_MAJOR}
    CLEAN_DIRECT_OUTPUT 1
)

ADD_DEPENDENCIES(${CAPN_LIB_NAME} jansson)

INSTALL(TARGETS ${CAPN_LIB_NAME}
    RUNTIME DESTINATION ${CAPN_INSTALL_PATH_BIN}
    LIBRARY DESTINATION ${CAPN_INSTALL_PATH_LIB}
    ARCHIVE DESTINATION ${CAPN_INSTALL_PATH_LIB}
)

INSTALL(FILES ${CAPN_PUBLIC_HEADER_FILES} DESTINATION ${CAPN_INSTALL_PATH_INCLUDES})
